#ifndef _DWMRICORE_DWI_H
#define _DWMRICORE_DWI_H

#include "Point3F.h"
#include "Point3I.h"
#include "defines.h"

#include <stdlib.h>

// TEEM
#include <teem/nrrd.h>
#include <teem/biff.h>

class CDWI
{
public:
	float *m_pDWI;
	uint m_w;
	uint m_h;
	uint m_d;
	uint m_n;
	uint m_m;			/* assume first m_m images are S0(B0) images */

	float *m_pS0;

	CVector3F *m_pDiffusionGradients;
	float m_bValue;

public:
	CDWI();
	~CDWI();

public:
	// open the DWI in Nrrd format
	int OpenDWIFile(const char *pathname, FILE *fp = stdout);
	// save the DWI as Nrrd format (need imporvement)
	int SaveDWIFile(const char *pathname, FILE *fp = stdout);

	// create a DWI 
	int CreateDWI(const uint n, const uint w, const uint h, const uint d, const float *dwi = NULL);

	// return the pointer of the DWI data
	float *GetDWIData() { return m_pDWI; }

	// return the pointer of the diffusion gradients
	CVector3F *GetDiffusionGradients() { return m_pDiffusionGradients; }

	// use the following interface to get the DWI value 
	// of a particular position in the volume
	void GetDWI(const float x, const float y, const float z, float *dwi) const;
	void GetDWI(const CPoint3F &p, float *dwi) const;
	void GetDWI(const CPoint3F *p, float *dwi) const;

	void GetDWIFast(const uint x, const uint y, const uint z, float *dwi) const;
	void GetDWIFast(const CPoint3I &p, float *dwi) const;
	void GetDWIFast(const CPoint3I *p, float *dwi) const;
	void GetDWIFast(const uint index, float *dwi) const;

	// set DWI value
	void SetDWI(const uint x, const uint y, const uint z, const float *dwi);

	// get B value
	float GetBValue() { return m_bValue; }

	// get S0
	float GetS0(const uint i) const { return m_pS0[i]; }
	float GetS0(const float x, const float y, const float z) const;
	float GetS0(const CPoint3F &p) const;
	// get non-S0
	void GetNS0(const uint index, float *dwi) const;
	void GetNS0(const float x, const float y, const float z, float *dwi) const;
	void GetNS0(const CPoint3F &p, float *dwi) const;

	// use the following interface to get the size of the DWI volume
	uint GetWidth() { return m_w; }
	uint GetHeight() { return m_h; }
	uint GetDepth() { return m_d; }
	uint GetN() { return m_n; }
	uint GetM() { return m_m; }

	bool HasData() { 
		if (m_pDWI)
			return true; 
		else
			return false;
	}
};

#endif